/*
 * AnalizeButton.java
 * 
 * Created on Mar 11, 2009, 10:25:21 PM
 * 
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package portfolio.stock.analize;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import misellanea.Miscellanea;
import misellanea.MiscellaneaDB;
import portfolio.dbHost.dataBases.dbTable.Table;
import portfolio.dbHost.project.Project;
import portfolio.dbHost.project.attributes.InputAttribs;
import portfolio.dbHost.project.attributes.TimeLine;
import portfolio.mainScreen;
import portfolio.stock.ConfigureSVMPanel;
import preprocess.Preprocess;

/**
 *
 * @author ACA
 */
    public class AnalizeButtonAction implements ActionListener //extends AbstractAction
    {
        private ConfigureSVMPanel selectRef;
        private mainScreen        mainFrame;
        private Project           project = null;
        
        private AnalizeArguments analizeArguments = null;
        
        private Vector      vTableHeader    = null;
        private String      sStockName      = null;
        
        private int    iTerm         = 0;
        private int    iColumnsShift = 0;
        private String sDBName       = null;
        private String sIndexSelect  = null;
        private String sFrom         = null;
        private String sWhere        = null;
        private String sOrderBy      = null;

        /**
         * 
         * @param mainFrameParam 
         * @param frameParam 
         */
        public AnalizeButtonAction (mainScreen        mainFrameParam,
                                    JButton           jAnalizeButtonParam,
                                    ConfigureSVMPanel frameParam,
                                    String            sStockNameParam,
                                    Vector            vTableHeaderParam) throws Exception 
        {
            mainFrame              = mainFrameParam;
            JButton jAnalizeButton = jAnalizeButtonParam;
            jAnalizeButton.addActionListener(this);
            project = mainFrame.getDBLoggedHost().getProject();

            String [] sTimeLine = project.getTimeline().get ();
            Integer ITerm = new Integer (sTimeLine [TimeLine.TIMELINE_TERM]);
            iTerm = ITerm.intValue(); // project.getTimeline().getTerm();
            String [] sExcludeColumns = project.getExcludeColumns().get();
            iColumnsShift = sExcludeColumns.length; // NOT TRUE // +1; // <0j0> Added 1 more shift because the independent variable

            this.resetAnalizeButtonAction (frameParam, sStockNameParam, vTableHeaderParam);
        }
        /**
         * 
         */
        public void resetAnalizeButtonAction (ConfigureSVMPanel frameParam, String sStockNameParam, Vector vTableHeaderParam) throws Exception 
        {
            selectRef              = frameParam;
            sStockName             = sStockNameParam;
            vTableHeader           = vTableHeaderParam;
            
            project = mainFrame.getDBLoggedHost().getProject();
            InputAttribs tmpAttribs   = project.getInputAttribs();
            String [] sInputAttribs = tmpAttribs.get();
            sDBName      = sInputAttribs [InputAttribs.INPUTATTRIBS_INPUTDB]; //tmpAttribs.getInputDB();

            String []    sExcludeCols = project.getExcludeColumns().get();
            String       sTrainSet    = sInputAttribs [InputAttribs.INPUTATTRIBS_TRAINSET]; //tmpAttribs.getTrainSet();
            String []    sExcludeTbls = project.getExcludeTables().get();
            String []    sTimeLine    = project.getTimeline().get ();
            String sDateIniParam      = sTimeLine [TimeLine.TIMELINE_BEGINDATE]; //project.getTimeline().getBeginDate();
            if (!sDateIniParam.contains("'"))
                sDateIniParam = "'" + sDateIniParam + "'";
            String sDateEndParam = sTimeLine [TimeLine.TIMELINE_ENDDATE]; // mainFrame.getDBLoggedHost().getProject().getTimeline().getEndDate();
            if (!sDateEndParam.contains("'"))
                sDateEndParam = "'" + sDateEndParam + "'";                

            String [] sIncludeTbls = MiscellaneaDB.getIncludeTables(sStockName, sExcludeTbls);

            String sYOrderedAxe = MiscellaneaDB.getYOrderedAxe (sStockName, sExcludeCols, sTrainSet);
            sFrom        = MiscellaneaDB.from           (sIncludeTbls);
            sWhere       = MiscellaneaDB.whereDates     (sDateIniParam, sDateEndParam, sStockName, sExcludeCols [0], sIncludeTbls);
            sOrderBy     = MiscellaneaDB.orderBy        (sStockName, sExcludeCols);

            String sColumnSelect = vTableHeaderParam.toString ();
            sColumnSelect = sColumnSelect.substring (1, sColumnSelect.length () -1);
            sIndexSelect = sYOrderedAxe + sColumnSelect;
            
        }
        /*******************************************************************/
        /* This method is called when the button is pressed                */
        /*******************************************************************/
        public void actionPerformed(ActionEvent evt) {

            try {
                mainFrame.getPlotPanel().removeAll();
                mainFrame.getPlotPanel().revalidate();
                mainFrame.getResultsPanel().removeAll();
                mainFrame.getResultsPanel().revalidate();
                mainFrame.displayMessage("portfolio.stock.analize.AnalizeButtonAction.actionPerformed 116", "Alnalizis of " + sStockName + " started.");
                
                Connection dbConnection  = mainFrame.getDBLoggedHost().getConnection();
                ResultSet resultSet = Table.getQuery (dbConnection, sDBName, sIndexSelect, sFrom, sWhere, sOrderBy);
                resultSet.last();
                int iRowCount = resultSet.getRow() - iTerm;
                resultSet.first();
                if (iRowCount <= 0) {
                    new Exception  ("Error: no query submited.");
                } 
                /////////////////////////////////////////////////////
                resultSet.first();
                int [] iSelectedRows = this.setTermDependentSelectedRows (iRowCount, iTerm);

                mainFrame.displayMessage ("AnalizeButtonAction.AnalizeButtonAction 113", "Amount of selected rows: " + iSelectedRows.length  + "." +
                                            " Term: " + iTerm  + "." + " Training limits: " + 
                                            ((iSelectedRows.length >0)?iSelectedRows [0]:0) + ":" +
                                            ((iSelectedRows.length >0)?iSelectedRows [iSelectedRows.length -1]:0));

                double [][] dResultSetMatrix = Table.transferResultSet2Matrix (resultSet, iColumnsShift); // Full copy of table in double format.
                // Matrix with dTable columns length
                // dTable - term height
                // first column shareVal shifted down "term" registers.
                double [][] dWorkMatrix       = Miscellanea.getWorkMatrix  (dResultSetMatrix, iTerm);
                double [][] dTmpTrainMatrix   = Miscellanea.getTrainMatrix (dWorkMatrix, iSelectedRows);

                double [][] dXTrainMatrix     = Miscellanea.getXMatrix (dTmpTrainMatrix);
                double [][] dXPredictMatrix   = Miscellanea.getXMatrix (dResultSetMatrix);
                double []   dYTargetVector    = Miscellanea.getYVector (dTmpTrainMatrix);
                double []   dYPredictVector   = Miscellanea.getYVector (dResultSetMatrix);
                Vector      vTimeLine         = TimeLine.getVector (resultSet, iTerm);
                ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                this.setAnalizeArguments ();
//                analizeArguments                 = new AnalizeArguments ();
//                analizeArguments.preprocess      = selectRef.getPreprocessOK().isSelected();
//                analizeArguments.preprocess_type = selectRef.getPreprocessGroup();
//                analizeArguments.components      = selectRef.getComponentsConfig ();
//                analizeArguments.iterations      = selectRef.getIterationsConfig ();
//
//                analizeArguments.svm_type    = selectRef.getTypeGroup    ();
//                analizeArguments.kernel_type = selectRef.getKernelGroup  ();
//
//                analizeArguments.degree      = selectRef.getDegreeConfig ();
//                analizeArguments.gamma       = selectRef.getGammaConfig  ();
//                analizeArguments.coef0       = selectRef.getCoef0Config  ();
//                analizeArguments.C           = selectRef.getCostConfig   ();
//                analizeArguments.nu          = selectRef.getNuConfig     ();
//                analizeArguments.p           = selectRef.getElossConfig  ();
//                analizeArguments.eps         = selectRef.getETolConfig   ();
//                analizeArguments.shrinking   = selectRef.getShrinking    ();

                double [][] dTrainMatrix = null;
                double [][] dXPredPre    = null;
                Preprocess  preprocess1  = null;
                Preprocess  preprocess2  = null;

                if (selectRef.getPreprocessOK().isSelected()) {
                    //System.out.println ("Selected " + selectRef.getPreprocessGroup ()+" <<<"+dXTrainMatrix[0].length+"<<<<<<<<<<<<<<<<<");
                    int iComponents = analizeArguments.components; //selectRef.getComponentsConfig ();
                    int iComponentsTotal = vTableHeader.size();
                    if (iComponents > iComponentsTotal) {
                        throw new Exception ("Error: Components size not allowed");
                    }
                    int iIterations = analizeArguments.iterations; //selectRef.getIterationsConfig ();

                    preprocess1 = new Preprocess (iComponents, iIterations);
                    preprocess2 = new Preprocess (iComponents, iIterations);                       

                    double [][] dTmpTre = preprocess1.PCAPreProcess (dXTrainMatrix);
                    double [][] dTmpPre = preprocess2.PCAPreProcess (dXPredictMatrix);
                    if ("ICA".equals(analizeArguments.preprocess_type)) {
                        preprocess1.ICAPreProcess (dTmpTre);
                        preprocess2.ICAPreProcess (dTmpPre);
                        dTrainMatrix = preprocess1.getIndependentComponents(dTmpTre);
                        dXPredPre    = preprocess2.getIndependentComponents(dTmpPre); 
                    }  else if ("PCA".equals(analizeArguments.preprocess_type)) {
                        dTrainMatrix = dTmpTre;
                        dXPredPre    = dTmpPre;
                    }

                    //dCorrMtx = Miscellanea.getCorrelationMtx (dXPredictMatrix, dXPredPre);
                } else {
                    dTrainMatrix = dXTrainMatrix;
                    dXPredPre    = dXPredictMatrix;
                    mainFrame.displayMessage("portfolio.stock.analize.AnalizeButtonAction.actionPerformed 200", "NO Preprocess Selected.");
                }

                SvmRegression svmReg = new SvmRegression (analizeArguments, dYTargetVector, dTrainMatrix);
                svmReg.readSvmProblem ();
                String sSvmMsg = svmReg.svmCheckParameter();
                if (sSvmMsg != null) {
                    throw new Exception ("Error: "+ sSvmMsg);
                }
                svmReg.svmTrain ();

                double []   dYPredicted = svmReg.svmPredict (dXPredPre);
//////////////////////////////////////////                
                String [] sTimeLine = project.getTimeline().get();
                Integer ITerm = new Integer (sTimeLine [TimeLine.TIMELINE_TERM]);
////////////////////////////////////////////////////////////
                int iTerm = ITerm.intValue (); //project.getTimeline().getTerm();
                double [][] dTimeSeries = this.createTimeSeries (vTimeLine, iTerm, dYPredictVector, dYPredicted);

                new DrawPanel ( sStockName, 
                                dTimeSeries,
                                vTableHeader,
                                iTerm, 
                                dYTargetVector.length, 
                                vTimeLine,
                                700, 400, 
                                mainFrame, 
                                "Plot data", 
                                "Data Train",
                                preprocess2);
                new DisplayResults(mainFrame, 
                                  sStockName, 
                                  iTerm, 
                                  vTimeLine, 
                                  dTimeSeries,
                                  vTableHeader,
                                  selectRef,
                                  preprocess2);
                
            } catch (Exception e) {
                JOptionPane.showMessageDialog (null, e);
            }                
        }

        /********************************************************************/
        private double [][] createTimeSeries (Vector vTimeLineParam,
                                              int      iTerm,
                                              double [] dTimeSeries1, 
                                              double [] dTimeSeries2)
        {
            int    iRowLen = vTimeLineParam.size();
            double dTimeSeries [][] = new double [iRowLen][2];

            for (int i = 0; i < iRowLen; i++) {
                if (i < dTimeSeries1.length) {
                    dTimeSeries [i][0] = dTimeSeries1 [i];
                    if (i < iTerm) {
                        dTimeSeries [i][1] = 0;
                    } else {
                        dTimeSeries [i][1] = dTimeSeries2 [i -iTerm];
                    }
                } else {
                    dTimeSeries [i][0] = 0;
                    dTimeSeries [i][1] = dTimeSeries2 [i -iTerm];
                }
            }
            return dTimeSeries;
        }
         /**
          * 
          */
        private int [] setTermDependentSelectedRows (int iRowCount, int iTermParam) throws Exception
        {
            //int iRowCount = resultSetParam.getRow();
            int iNumSelectedRows = iRowCount - iTermParam;
            int [] iSelectedRows = new int [iNumSelectedRows];
            for (int iIdx = 0; iIdx < iNumSelectedRows; iIdx++) {
                iSelectedRows [iIdx] = iIdx;
            }
            if (iSelectedRows == null && iTermParam == 0) {
                return null;
            } else if (iSelectedRows == null && iTermParam != 0) {
                new Exception ("Error: training set beyond allowed limits. ");
            }  else if (iSelectedRows.length <= 0 && iTermParam != 0) {
                new Exception ("Error: training set beyond allowed limits. ");
            }                
            if (iSelectedRows.length + iTermParam > iRowCount) {
                new Exception ("Error: term "+ iTermParam + " < selected rows needed to train.");
            }
            if (iSelectedRows.length == 0 && iRowCount - iTermParam != iRowCount) {
                new Exception ("Error: training set beyond allowed limits. ");
            }

            return iSelectedRows;
        }
        /**
         * 
         */
        private AnalizeArguments setAnalizeArguments () throws Exception 
        {
            analizeArguments                 = new AnalizeArguments ();
            analizeArguments.preprocess      = selectRef.getPreprocessOK().isSelected();
            analizeArguments.preprocess_type = selectRef.getPreprocessGroup();
            analizeArguments.components      = selectRef.getComponentsConfig ();
            analizeArguments.iterations      = selectRef.getIterationsConfig ();

            analizeArguments.svm_type    = selectRef.getTypeGroup    ();
            analizeArguments.kernel_type = selectRef.getKernelGroup  ();

            analizeArguments.degree      = selectRef.getDegreeConfig ();
            analizeArguments.gamma       = selectRef.getGammaConfig  ();
            analizeArguments.coef0       = selectRef.getCoef0Config  ();
            analizeArguments.C           = selectRef.getCostConfig   ();
            analizeArguments.nu          = selectRef.getNuConfig     ();
            analizeArguments.p           = selectRef.getElossConfig  ();
            analizeArguments.eps         = selectRef.getETolConfig   ();
            analizeArguments.shrinking   = selectRef.getShrinking    ();

            return analizeArguments;
        }
    } /* End class submitButton::selectIndexes::IndexSelectionAction */
